home *** CD-ROM | disk | FTP | other *** search
/ MacTech 1 to 12 / MacTech-vol-1-12.toast / Source / MacTech® Magazine / Volume 06 - 1990 / 06.02 Feb 90 / Mouse Source / TrackHilite.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-10-23  |  6.4 KB  |  240 lines  |  [TEXT/KAHL]

  1. /*                                            TrackHilite.c                                        */
  2. /*
  3.  * Copyright © 1989 Martin Minow. All rights reserved.
  4.  *
  5.  * These routines invert the selection or draw insertion
  6.  * point.  When called, _TrackPtr points to the locked
  7.  * TrackRecord.  These routines are not called directly
  8.  * by the application program.
  9.  */  
  10. #include "TrackEdit.h"
  11. #include "Color.h"
  12. #define TR    (*tr)
  13. #define NIL        0
  14.  
  15.  
  16. static void        invert_rect(
  17.                                 TrackPtr, LONGINT, LONGINT, LONGINT);
  18.  
  19. /*
  20.  * _Track_hilite(track_ptr, start, end)
  21.  * Invert the selection between start and end, both
  22.  * given as indices into *(_TrackPtr->string). Note:
  23.  * start is not necessarily "earlier" than end.
  24.  */
  25. void
  26. _Track_hilite(tr, dot_start, dot_end)
  27. register TrackPtr    tr;
  28. DOT                                dot_start;
  29. DOT                                dot_end;
  30. {
  31.         LONGINT                        row_start, row_end;
  32.         INTEGER                        col_start, col_end, start, end;
  33.         DOT                                temp;
  34.  
  35.         /*
  36.          * If there is no selection, there's nothing to
  37.          * invert.  Note that we're only called if the
  38.          * window is active.
  39.          */
  40.         if (dot_start == dot_end)
  41.             return;                        /* No hiliting needed                        */
  42.         /*
  43.          * It's a real selection: normalize the selection
  44.          * so start is north-east of end and convert to
  45.          * pixel coordinates.
  46.          */
  47.         if (dot_start > dot_end) {
  48.             temp = dot_start;
  49.             dot_start = dot_end;
  50.             dot_end = temp;
  51.         }
  52.         row_start = _Track_row(tr, dot_start);
  53.         row_end   = _Track_row(tr, dot_end);
  54.         col_start = _Track_dot_to_col(tr, dot_start);
  55.         col_end   = _Track_dot_to_col(tr, dot_end); 
  56.         /*
  57.          * If everything is on one row, do it.
  58.          */
  59.         if (row_start == row_end)
  60.             invert_rect(tr, row_start, col_start, col_end);
  61.         else {
  62.             /*
  63.              * We have several lines to invert. Start with the
  64.              * right end of the first line.
  65.              */
  66.             end = _Track_dot_to_eol(tr, row_start);
  67.             invert_rect(tr, row_start, col_start, end);
  68.             /*
  69.              * Do any complete rows.  This can be optimized
  70.              * for many applications.
  71.              */
  72.             while (++row_start < row_end) {
  73.                 start = _Track_dot_to_bol(tr, row_start);
  74.                 end   = _Track_dot_to_eol(tr, row_start);
  75.                 invert_rect(tr, row_start, start, end);
  76.             }
  77.             /*
  78.              * Finally, do the last row.
  79.              */
  80.             start = _Track_dot_to_bol(tr, row_end);
  81.             invert_rect(tr, row_end, start, col_end);
  82.         }
  83. }
  84.  
  85. /*
  86.  * _Track_caret(track_ptr, desired_state)
  87.  * Draw (or erase) the selection marker at selStart.
  88.  * (Make sure it's in the mouse row.)
  89.  * Call the user's caret routine if requested.
  90.  */
  91. void
  92. _Track_caret(tr, state)
  93. register TrackPtr    tr;
  94. INTEGER                        state;
  95. {
  96.         /*
  97.          * If there is a real selection, or the text is not
  98.          * active, just return.  Likewise if the caret state
  99.          * shouldn't change. Otherwise, invert the caret.
  100.          */
  101.         if (!_Track_is_set(tr, _Track_is_active)
  102.          || TR.selStart != TR.selEnd)
  103.             ;                                /* No caret wanted                            */
  104.         else if (state == _Track_caret_on
  105.          && _Track_is_set(tr, _Track_caret_visible))
  106.              ;                                /* Want on and it's still on        */
  107.         else if (state == _Track_caret_off
  108.          && !_Track_is_set(tr, _Track_caret_visible))
  109.             ;                                /* Want off and it's still off    */
  110.         else {
  111.             /*
  112.              * Invert the caret on screen.
  113.              */
  114.             _Track_flip(tr, _Track_caret_visible);
  115.             _Track_invert_caret(tr);
  116.         }
  117. }
  118.  
  119. void
  120. _Track_invert_caret(tr)
  121. register TrackPtr    tr;
  122. {
  123.         PenState                    pen_state;
  124.         Rect                            caret;
  125.         LONGINT                        row;
  126.         LONGINT                        col;
  127.         DOT                                dot;
  128.         
  129.         if (TR.selStart != TR.selEnd)
  130.             return;
  131.         row = _Track_row(tr, TR.selStart);
  132.         col = _Track_dot_to_col(tr, TR.selStart);
  133.         if (col == TR.viewRect.left && TR.selRow < row) {
  134.             /*
  135.              * Hack: if dot is at the start of a line, the true
  136.              * mouse point might be at the end of the previous
  137.              * line.  In this case, the mouse row won't equal
  138.              * dot's row.  Force the caret point so it's to
  139.              * the right of the last character on the previous
  140.              * row.
  141.              * Further hack, if selStart is at the end of the
  142.              * text, look at the last character.  If it's
  143.              * a <return>, caret is really on the next line.
  144.              * Grumble.
  145.              */
  146.             if (TR.selStart != (DOT) TR.textLength
  147.              || TR.textLength == 0
  148.              || (*TR.hText)[TR.selStart - 1] != '\r') { 
  149.                 row = TR.selRow;
  150.                 col = _Track_dot_to_col(tr, TR.selStart - 1)  
  151.                     + CharWidth((*TR.hText)[TR.selStart - 1]);
  152.             }
  153.         }
  154.         /*
  155.          * Convert to the equivalent pixel coordinate and
  156.          * draw it if it might be visible.
  157.          */
  158.         row = _Track_row_pixel(tr, row);
  159.         if (row < (LONGINT) TR.viewRect.top - TR.lineHeight
  160.          || row > (LONGINT) TR.viewRect.bottom + TR.lineHeight
  161.          || col < (LONGINT) TR.viewRect.left
  162.          || col > (LONGINT) TR.viewRect.right)
  163.              return;                                            /* Invisible                    */
  164.         if (TR.caretHook != NIL) {
  165.             SetRect(
  166.                 &caret,
  167.                 (int) col,
  168.                 (int) row - TR.fontAscent,
  169.                 (int) col + 1,
  170.                 (int) row + TR.fontDescent
  171.             );
  172.             CallPascal(&caret, tr, TR.caretHook);
  173.         }
  174.         else {
  175.             /*
  176.              * Fancy "caret."
  177.              */
  178.             GetPenState(&pen_state);
  179.             PenNormal();
  180.             PenMode(patXor);
  181.             MoveTo(col, (int) row - TR.fontAscent);
  182.             Line(0, TR.fontAscent);
  183.             Line(-TR.fontDescent, TR.fontDescent);
  184.             Move(TR.fontDescent * 2, 0);
  185.             Line(-TR.fontDescent, -TR.fontDescent);
  186.             SetPenState(&pen_state);
  187.         }
  188. }
  189.  
  190. /*
  191.  * invert_rect(tr, row, start, end)
  192.  * Invert the screen rectangle on the specified row
  193.  * between the specified horizontal pixels.
  194.  * Note: end points just to the right of the last pixel
  195.  * to invert.  Also, note that this routine understands
  196.  * that points are normalized, extending them in the
  197.  * appropriate direction to cover the character.
  198.  */
  199. static void
  200. invert_rect(tr, row, start, end)
  201. register TrackPtr    tr;
  202. LONGINT                                row;
  203. LONGINT                                start;
  204. LONGINT                                end;
  205. {
  206.         Rect                            box;
  207.  
  208.         /*
  209.          * Convert row to the equivalent pixel coordinate.
  210.          */
  211.         row = _Track_row_pixel(tr, row);
  212.         if (start == end
  213.          || row < (LONGINT) TR.viewRect.top - TR.lineHeight
  214.          || row > (LONGINT) TR.viewRect.bottom + TR.lineHeight)
  215.             return;
  216.         if (start < (LONGINT) TR.viewRect.left)
  217.             start = (LONGINT) TR.viewRect.left;
  218.         if (end > (LONGINT) TR.viewRect.right)
  219.             end = (LONGINT) TR.viewRect.right;
  220.         if (start >= end)
  221.             return;
  222.         box.left = (int) start;
  223.         box.right = (int) end;
  224.         box.top = (int) row + TR.fontDescent - TR.lineHeight;
  225.         box.bottom = (int) row + TR.fontDescent;
  226.         if (SectRect(&box, &TR.viewRect, &box)) {
  227.             if (TR.highHook != NIL)                            /* Use user's    */
  228.                 CallPascal(&box, tr, TR.highHook);    /*  hiliter    */
  229.             else {
  230.                 /*
  231.                  * Properly hilite color screens (ok for b/w, too)
  232.                  * See Inside Mac V, p. 62.
  233.                  */ 
  234.                 HiliteMode &= ~(1 << hiliteBit);
  235.                 InvertRect(&box);
  236.             }
  237.         }
  238. }
  239.  
  240.